// NextUseRegAllocator.h
// A registers allocator based on Next-use

#ifndef NEXTUSEREGALLOCATOR_H
#define NEXTUSEREGALLOCATOR_H

#include "crossbit/common.h"
#include "crossbit/RegAllocator.h"
#include <vector>
#include <queue>
#include <map>
#include <deque>
#include <set>

namespace crossbit {

	// class VBlock;

	class NextUseRegAllocator : public RegAllocator {

		public:
			NextUseRegAllocator(XTUint8 num_regs, CBOfSpillIn cb_spill_in, CBOfSpillOut cb_spill_out, CBOfRegToReg cb_regtoreg) : RegAllocator(num_regs, cb_spill_in, cb_spill_out, cb_regtoreg)
		{	
		}

			virtual ~NextUseRegAllocator()
			{}

			// Allocate target register for virtual register
			virtual XTRegNum regAlloc(XTRegNum vreg, RegAccessMode mode);	        
			// Force allocate target register "expect" to "vreg"
			virtual XTRegNum regAllocForce(XTRegNum vreg, XTRegNum expect, RegAccessMode mode);
			// Force "vreg" NOT to be allocated to "except"
			virtual XTRegNum regAllocForceExcept(XTRegNum vreg, XTRegNum except, RegAccessMode mode);

			virtual void regAllocReserve(XTRegNum reg);
			virtual void regAllocRelease(XTRegNum reg);

			// this is a auxilary function used for debugging
			void printNextUseInfo();
			void unmapIfNoNextUse(XTRegNum vreg);

			virtual void init(VBlock *vb);
			virtual void phaseTask();
			void incrementVinstSeq()
			{
				++vinst_seq;
				//		UTIL::XTMemset( vreg_spilled , 0 , sizeof( vreg_spilled ) ); modified by lixiaolong,this is useless.
				for( XTRegNum i = 0 ; i < 8 ; i ++ ){
					if( ra_reg_table[i].status == ALLOCATED ){
						XTRegNum vreg = ra_reg_table[i].mapped_to;
						ra_vreg_spilled[vreg] = true;
						//printf("This is %d ALLOCATED with %d\n",i,vreg);
					}
				}
			}

		private:
			void collectNextUseInfo(VBlock *vb);

			virtual XTRegNum regSpillOut(XTRegNum vreg);

			/*typedef std::map < XTRegNum, struct RegUsage > RegUsageTable;
			  RegUsageTable ra_vreg_usg_tbl;	// virtual registers usage table
			  RegUsageTable ra_treg_usg_tbl;	// target/physical registers usage table
			  typedef std::map< XTRegNum, XTInt32 > NextUse;
			  typedef std::deque< NextUse >	  NextUseTable;
			  NextUseTable ra_next_use_tbl;

			  std::set<XTRegNum> ra_free_regs;// free registers available for allocation
			  td::vector<XTRegNum> ra_torelease_regs; // registers that will be released immediately after the current instruction's execution
			// */

			//Modified by suntingtao
			//vreg_used_list[50] is used to store the sequence of vregs used or defined in Vinst list.
			//the pair<XTInt32,RegAccessMode> stand for the sequece number and use mod(USE or DEF).
			const static XTInt32 MAX_VREG_NUM = 50;
			std::queue<std::pair<XTInt32,RegAccessMode> > ra_vreg_used_list[MAX_VREG_NUM];
			//The usage of the physical registers.
			// here 8 is the number of the register number of intel cup
			RegUsage  ra_reg_table[8];
			bool  ra_vreg_spilled[MAX_VREG_NUM];
	};

}

#endif
